﻿namespace HutongGames.PlayMakerEditor
{
    using HutongGames.PlayMaker;
    using System;
    using System.Collections.Generic;
    using UnityEditor;
    using UnityEngine;

    public class ActionSelector : EditorWindow
    {
        private System.Type afterSelected;
        private bool autoScroll;
        private System.Type beforeSelected;
        private float descriptionHeight;
        private readonly List<System.Type> filteredActions = new List<System.Type>();
        private readonly List<string> filteredCategories = new List<string>();
        private readonly List<string> filteredCategoryLookup = new List<string>();
        private bool focusSearchField;
        private System.Type mouseOverAction;
        private Vector2 mousePos;
        private System.Type prevAction;
        private FsmStateAction previewAction;
        private float previewActionGUIHeight;
        private Vector2 previewScrollPosition;
        private float previewScrollViewHeight;
        private int previousSelectedCategory;
        private string prevSearchString = "";
        private Vector2 scrollPosition;
        private float scrollViewHeight;
        private string searchString = "";
        private System.Type selectedAction;
        private Rect selectedRect;

        private void AddSelectedActionAfter()
        {
            if ((this.selectedAction != null) && (FsmEditor.SelectedState != null))
            {
                FsmEditor.StateInspector.AddActionAfterSelectedAction(this.selectedAction);
                this.FinishAddAction();
            }
        }

        private void AddSelectedActionBefore()
        {
            if ((this.selectedAction != null) && (FsmEditor.SelectedState != null))
            {
                FsmEditor.StateInspector.AddActionBeforeSelectedAction(this.selectedAction);
                this.FinishAddAction();
            }
        }

        private void AddSelectedActionToState()
        {
            if ((this.selectedAction != null) && (FsmEditor.SelectedState != null))
            {
                FsmEditor.StateInspector.AddAction(this.selectedAction);
                this.FinishAddAction();
            }
        }

        private void AddSelectedActionToTop()
        {
            if ((this.selectedAction != null) && (FsmEditor.SelectedState != null))
            {
                FsmEditor.StateInspector.AddActionToTop(this.selectedAction);
                this.FinishAddAction();
            }
        }

        private void BuildFilteredList()
        {
            this.prevSearchString = this.searchString;
            this.filteredActions.Clear();
            this.filteredCategories.Clear();
            this.filteredCategoryLookup.Clear();
            string str = this.searchString.ToUpper().Replace(" ", "");
            foreach (System.Type type in FsmEditorUtility.Actionslist)
            {
                if (FsmEditorUtility.GetActionLabel(type).ToUpper().Replace(" ", "").Contains(str))
                {
                    this.filteredActions.Add(type);
                    string item = FsmEditorUtility.ActionCategoryLookup[FsmEditorUtility.Actionslist.IndexOf(type)];
                    this.filteredCategoryLookup.Add(item);
                    if (!this.filteredCategories.Contains(item))
                    {
                        this.filteredCategories.Add(item);
                    }
                    this.filteredCategories.Sort();
                }
            }
        }

        private void DoActionButton(System.Type actionType)
        {
            string actionLabel = FsmEditorUtility.GetActionLabel(actionType);
            GUIStyle style = (this.selectedAction == actionType) ? FsmEditorStyles.ActionItemSelected : FsmEditorStyles.ActionItem;
            GUILayout.Box(actionLabel, style, new GUILayoutOption[0]);
            if (GUILayoutUtility.GetLastRect().Contains(this.mousePos))
            {
                this.mouseOverAction = actionType;
            }
            if (this.mouseOverAction == actionType)
            {
                switch (Event.current.type)
                {
                    case EventType.MouseDown:
                        this.SelectAction(actionType);
                        if ((Event.current.button == 1) || EditorGUI.actionKey)
                        {
                            this.GenerateContextMenu().ShowAsContext();
                        }
                        if (Event.current.clickCount > 1)
                        {
                            this.AddSelectedActionToState();
                        }
                        GUIUtility.ExitGUI();
                        return;

                    case EventType.MouseDrag:
                        this.DragAction(actionType);
                        GUIUtility.ExitGUI();
                        return;
                }
            }
            if (actionType == this.selectedAction)
            {
                this.beforeSelected = this.prevAction;
                if (Event.current.type == EventType.Repaint)
                {
                    this.selectedRect = GUILayoutUtility.GetLastRect();
                    this.selectedRect.y -= this.scrollPosition.y;
                }
            }
            if (this.prevAction == this.selectedAction)
            {
                this.afterSelected = actionType;
            }
            this.prevAction = actionType;
        }

        private void DoActionHierarchyGUI()
        {
            for (int i = 0; i < FsmEditorUtility.ActionCategoryList.Count; i++)
            {
                string text = FsmEditorUtility.ActionCategoryList[i];
                this.previousSelectedCategory = FsmEditorSettings.SelectedActionCategory;
                if (GUILayout.Toggle(FsmEditorSettings.SelectedActionCategory == i, text, "Button", new GUILayoutOption[0]))
                {
                    FsmEditorSettings.SelectedActionCategory = i;
                    if (this.previousSelectedCategory != FsmEditorSettings.SelectedActionCategory)
                    {
                        this.selectedAction = null;
                        FsmEditorSettings.SaveSettings();
                    }
                }
                if (FsmEditorSettings.SelectedActionCategory == i)
                {
                    this.DoActionSelectorGUI(text);
                }
            }
        }

        private void DoActionList()
        {
            this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, new GUILayoutOption[0]);
            this.mouseOverAction = null;
            if (Event.current.isMouse)
            {
                this.mousePos = Event.current.mousePosition;
            }
            if (string.IsNullOrEmpty(this.searchString))
            {
                this.DoActionHierarchyGUI();
            }
            else
            {
                this.DoFilteredList();
            }
            GUILayout.EndScrollView();
            this.DoAutoScroll();
        }

        private void DoActionPreview()
        {
            EditorGUIUtility.LookLikeControls(150f);
            EditorGUILayout.Space();
            FsmEditorGUILayout.Divider(new GUILayoutOption[0]);
            this.previewScrollViewHeight = Mathf.Min((base.position.height - 150f) - this.descriptionHeight, this.previewActionGUIHeight);
            this.previewScrollPosition = EditorGUILayout.BeginScrollView(this.previewScrollPosition, new GUILayoutOption[] { GUILayout.Height(this.previewScrollViewHeight) });
            GUILayout.BeginVertical(new GUILayoutOption[0]);
            bool enabled = GUI.enabled;
            GUI.enabled = false;
            FsmEditor.ActionEditor.OnGUI(this.previewAction, false, true);
            GUI.enabled = enabled;
            GUILayout.EndVertical();
            if (Event.current.type == EventType.Repaint)
            {
                float previewActionGUIHeight = this.previewActionGUIHeight;
                this.previewActionGUIHeight = GUILayoutUtility.GetLastRect().height + 10f;
                if (Math.Abs((float) (this.previewActionGUIHeight - previewActionGUIHeight)) > 1f)
                {
                    base.Repaint();
                    this.autoScroll = true;
                }
            }
            EditorGUILayout.EndScrollView();
            FsmEditorGUILayout.Divider(new GUILayoutOption[0]);
            EditorGUILayout.Space();
        }

        private void DoActionSelectorGUI(string categoryName)
        {
            for (int i = 0; i < FsmEditorUtility.Actionslist.Count; i++)
            {
                if (FsmEditorUtility.ActionCategoryLookup[i] == categoryName)
                {
                    System.Type actionType = FsmEditorUtility.Actionslist[i];
                    this.DoActionButton(actionType);
                }
            }
        }

        private void DoAutoScroll()
        {
            if ((Event.current.type == EventType.Repaint) && this.autoScroll)
            {
                this.scrollViewHeight = GUILayoutUtility.GetLastRect().height;
                if (this.selectedRect.y < 0f)
                {
                    this.scrollPosition.y += this.selectedRect.y;
                    base.Repaint();
                }
                else if ((this.selectedRect.y + this.selectedRect.height) > this.scrollViewHeight)
                {
                    this.scrollPosition.y += (this.selectedRect.y + this.selectedRect.height) - this.scrollViewHeight;
                    base.Repaint();
                }
                this.autoScroll = false;
            }
        }

        private void DoBottomPanel()
        {
            FsmEditorGUILayout.Divider(new GUILayoutOption[0]);
            if (this.selectedAction != null)
            {
                GUILayout.BeginHorizontal(new GUILayoutOption[0]);
                GUILayout.Label(FsmEditorUtility.GetActionLabel(this.selectedAction), EditorStyles.boldLabel, new GUILayoutOption[0]);
                GUILayout.FlexibleSpace();
                if (FsmEditorGUILayout.HelpButton("Online Help"))
                {
                    EditorCommands.OpenWikiPage(this.previewAction);
                }
                GUILayout.EndHorizontal();
                GUILayout.Box(FsmEditorUtility.GetTooltipAttribute(this.selectedAction), FsmEditorStyles.LabelWithWordWrap, new GUILayoutOption[0]);
                if (Event.current.type == EventType.Repaint)
                {
                    this.descriptionHeight = GUILayoutUtility.GetLastRect().height;
                }
                if (FsmEditorSettings.ShowActionPreview)
                {
                    this.DoActionPreview();
                }
            }
            GUILayout.BeginHorizontal(new GUILayoutOption[0]);
            bool flag = GUILayout.Toggle(FsmEditorSettings.ShowActionPreview, "Preview", new GUILayoutOption[0]);
            if (flag != FsmEditorSettings.ShowActionPreview)
            {
                FsmEditorSettings.ShowActionPreview = flag;
                FsmEditorSettings.SaveSettings();
            }
            if ((FsmEditor.SelectedState == null) || (this.selectedAction == null))
            {
                GUI.enabled = false;
            }
            if (GUILayout.Button(new GUIContent("Add Action To State", "Add the selected Action to the selected State. NOTE: You can also drag and drop the actions."), new GUILayoutOption[0]))
            {
                this.AddSelectedActionToState();
            }
            GUILayout.EndHorizontal();
            EditorGUILayout.Space();
        }

        private void DoFilteredList()
        {
            foreach (string str in this.filteredCategories)
            {
                GUILayout.Button(str, new GUILayoutOption[0]);
                for (int i = 0; i < this.filteredActions.Count; i++)
                {
                    if (this.filteredCategoryLookup[i] == str)
                    {
                        System.Type actionType = this.filteredActions[i];
                        this.DoActionButton(actionType);
                    }
                }
            }
        }

        private void DoToolbar()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, new GUILayoutOption[0]);
            GUI.SetNextControlName("ActionBrowserSearchField");
            this.searchString = GUILayout.TextField(this.searchString, EditorStyles.toolbarTextField, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
            if (this.focusSearchField)
            {
                GUI.FocusControl("ActionBrowserSearchField");
                this.focusSearchField = false;
            }
            if ((this.searchString != this.prevSearchString) && !string.IsNullOrEmpty(this.searchString))
            {
                this.BuildFilteredList();
                this.SelectFirstFilteredAction();
                GUIUtility.ExitGUI();
            }
            if (FsmEditorGUILayout.ToolbarDeleteButton())
            {
                this.searchString = "";
                base.Repaint();
            }
            if (FsmEditorGUILayout.ToolbarSettingsButton())
            {
                this.GenerateSettingsMenu().ShowAsContext();
            }
            GUILayout.Space(-5f);
            EditorGUILayout.EndHorizontal();
        }

        private void DragAction(System.Type actionType)
        {
            DragAndDropManager.SetMode(DragAndDropManager.DragMode.AddAction);
            DragAndDrop.PrepareStartDrag();
            DragAndDrop.objectReferences = new UnityEngine.Object[0];
            DragAndDrop.SetGenericData("AddAction", this.selectedAction);
            DragAndDrop.StartDrag("Drag Action");
            Event.current.Use();
            this.SelectAction(actionType);
        }

        private void FinishAddAction()
        {
            if (FsmEditorSettings.CloseActionBrowserOnEnter)
            {
                base.Close();
                if (Event.current != null)
                {
                    GUIUtility.ExitGUI();
                }
            }
        }

        private GenericMenu GenerateContextMenu()
        {
            GenericMenu menu = new GenericMenu();
            if ((FsmEditor.SelectedFsm == null) || (FsmEditor.SelectedState == null))
            {
                menu.AddDisabledItem(new GUIContent("Select a state in the Graph View to add Actions"));
                return menu;
            }
            menu.AddItem(new GUIContent("Add to Top of Action List"), false, new GenericMenu.MenuFunction(this.AddSelectedActionToTop));
            if (FsmEditor.StateInspector.SelectedAction == null)
            {
                menu.AddDisabledItem(new GUIContent("Add Before Selected Action"));
                menu.AddDisabledItem(new GUIContent("Add After Selected Action"));
            }
            else
            {
                menu.AddItem(new GUIContent("Add Before Selected Action"), false, new GenericMenu.MenuFunction(this.AddSelectedActionBefore));
                menu.AddItem(new GUIContent("Add After Selected Action"), false, new GenericMenu.MenuFunction(this.AddSelectedActionAfter));
            }
            menu.AddItem(new GUIContent("Add to End of Action List"), false, new GenericMenu.MenuFunction(this.AddSelectedActionToState));
            return menu;
        }

        private GenericMenu GenerateSettingsMenu()
        {
            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("Show Preview"), FsmEditorSettings.ShowActionPreview, new GenericMenu.MenuFunction(this.ToggleShowActionPreview));
            menu.AddItem(new GUIContent("Hide Obsolete Actions"), FsmEditorSettings.HideObsoleteActions, new GenericMenu.MenuFunction(this.ToggleHideObsoleteActions));
            menu.AddItem(new GUIContent("Close Window After Adding Action"), FsmEditorSettings.CloseActionBrowserOnEnter, new GenericMenu.MenuFunction(ActionSelector.ToggleCloseActionBrowser));
            menu.AddItem(new GUIContent("Disable Window When Playing"), FsmEditorSettings.DisableActionBrowerWhenPlaying, new GenericMenu.MenuFunction(ActionSelector.ToggleDisableWindow));
            return menu;
        }

        private static void HandleDragAndDrop()
        {
            EventType type = Event.current.type;
            if (((type == EventType.DragUpdated) || (type == EventType.DragPerform)) && (DragAndDropManager.mode == DragAndDropManager.DragMode.MoveActions))
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.Move;
                if (type == EventType.DragPerform)
                {
                    DragAndDrop.AcceptDrag();
                    FsmEditor.StateInspector.DeleteSelectedActions(true);
                }
            }
        }

        private void HandleKeyboardInput()
        {
            this.prevAction = null;
            int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
            if (Event.current.GetTypeForControl(controlID) == EventType.KeyDown)
            {
                switch (Event.current.keyCode)
                {
                    case KeyCode.KeypadEnter:
                    case KeyCode.Return:
                        this.AddSelectedActionToState();
                        return;

                    case KeyCode.KeypadEquals:
                        return;

                    case KeyCode.UpArrow:
                        Event.current.Use();
                        this.SelectPrevious();
                        GUIUtility.ExitGUI();
                        return;

                    case KeyCode.DownArrow:
                        Event.current.Use();
                        this.SelectNext();
                        GUIUtility.ExitGUI();
                        return;

                    case KeyCode.Escape:
                        base.Close();
                        GUIUtility.ExitGUI();
                        return;
                }
            }
        }

        private void OnEnable()
        {
            base.title = "Actions";
            base.minSize = new Vector2(200f, 200f);
            base.autoRepaintOnSceneChange = true;
            this.focusSearchField = true;
            FsmEditorUtility.BuildActionsList();
            this.BuildFilteredList();
            base.Repaint();
        }

        private void OnFocus()
        {
            this.focusSearchField = true;
            this.BuildFilteredList();
            base.Repaint();
        }

        private void OnGUI()
        {
            if (FsmEditorGUILayout.ToolWindowsCommonGUI(this))
            {
                if (EditorApplication.isPlaying && FsmEditorSettings.DisableActionBrowerWhenPlaying)
                {
                    GUILayout.Label("Disabled when playing. See Action Browser Settings Menu.", new GUILayoutOption[0]);
                    FsmEditorSettings.DisableActionBrowerWhenPlaying = !GUILayout.Toggle(!FsmEditorSettings.DisableActionBrowerWhenPlaying, "Enable Action Browser When Playing", new GUILayoutOption[0]);
                    if (GUI.changed)
                    {
                        FsmEditorSettings.SaveSettings();
                    }
                }
                else
                {
                    this.HandleKeyboardInput();
                    this.DoToolbar();
                    this.DoActionList();
                    HandleDragAndDrop();
                    this.DoBottomPanel();
                }
            }
        }

        private void SelectAction(System.Type actionType)
        {
            if (actionType != this.selectedAction)
            {
                this.selectedAction = actionType;
                this.previewAction = (FsmStateAction) Activator.CreateInstance(actionType);
                this.previewAction.Reset();
                this.autoScroll = true;
                base.Repaint();
            }
        }

        private void SelectFirstFilteredAction()
        {
            if (this.filteredCategories.Count != 0)
            {
                string str = this.filteredCategories[0];
                for (int i = 0; i < this.filteredActions.Count; i++)
                {
                    if (this.filteredCategoryLookup[i] == str)
                    {
                        this.SelectAction(this.filteredActions[i]);
                        return;
                    }
                }
            }
        }

        private void SelectNext()
        {
            if ((this.selectedAction != null) && (this.afterSelected != null))
            {
                this.SelectAction(this.afterSelected);
            }
        }

        private void SelectPrevious()
        {
            if ((this.selectedAction != null) && (this.beforeSelected != null))
            {
                this.SelectAction(this.beforeSelected);
            }
        }

        private static void ToggleCloseActionBrowser()
        {
            FsmEditorSettings.CloseActionBrowserOnEnter = !FsmEditorSettings.CloseActionBrowserOnEnter;
            FsmEditorSettings.SaveSettings();
        }

        private static void ToggleDisableWindow()
        {
            FsmEditorSettings.DisableActionBrowerWhenPlaying = !FsmEditorSettings.DisableActionBrowerWhenPlaying;
            FsmEditorSettings.SaveSettings();
        }

        private void ToggleHideObsoleteActions()
        {
            FsmEditorSettings.HideObsoleteActions = !FsmEditorSettings.HideObsoleteActions;
            FsmEditorSettings.SaveSettings();
            FsmEditorUtility.BuildActionsList();
            this.BuildFilteredList();
            base.Repaint();
        }

        private void ToggleShowActionPreview()
        {
            FsmEditorSettings.ShowActionPreview = !FsmEditorSettings.ShowActionPreview;
            FsmEditorSettings.SaveSettings();
            base.Repaint();
        }
    }
}

